﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AdvplDoc.Model {

	class AdvplClass {
		public string name { 
            get {
                return this._name;
            }
            set {
                if (value != null && value.Length > 0)
                    this._name = value[0].ToString().ToUpper() + value.Substring(1);
                else
                    this._name = value;
            }
        }

        private string _name;
        public string parent { get; set; }
		public string description { get; set; }
        public Dictionary<string, AdvplMethod> constructors { get; set; }
		public List<AdvplMethod> methods { get; set; }
		public List<AdvplProperty> properties { get; set; }
		public List<string> observation { get; set; }
		public List<string> examples { get; set; }
        public string since { get; set; }
        public bool isDeprecated { get; set; }
        public string deprecatedInfo { get; set; }
		public List<string> seeAlso { get; set; }
        public AdvplClass parentClass { get; set; }

        public AdvplClass(string name, string parent)
            : this(name, parent, "", new List<string>(), new List<string>(), "", false, "", new List<string>()) {
        }


		public AdvplClass(	string name,
                            string parent,
							string description,
							List<string> observation,
							List<string> examples, 
							string since,
							bool isDeprecated,
							string deprecatedInfo,
							List<string> seeAlso) {
			this.name = name;
            this.parent = parent;
			this.description = description;
            this.constructors = new Dictionary<string, AdvplMethod>();
			this.methods = new List<AdvplMethod>();
			this.properties = new List<AdvplProperty>();
			this.observation = observation;
			this.examples = examples;
			this.since = since;
			this.isDeprecated = isDeprecated;
			this.deprecatedInfo = deprecatedInfo;
			this.seeAlso = seeAlso;
		}

        public void addConstructor(AdvplMethod method) {
            this.constructors.Add(method.name.ToUpper(), method);
        }

		public void addMethod(AdvplMethod method) {
			this.methods.Add(method);
		}

		public void addProperty(AdvplProperty attribute) {
			this.properties.Add(attribute);
		}

		public override string ToString() {
			return "Classe ADVPL " + this.name;
		}

        public List<AdvplClass> getHierarchy() {
            List<AdvplClass> hierarchy = new List<AdvplClass>();
            AdvplClass current = this;

            while (current != null) {
                hierarchy.Insert(0, current);
                
                current = current.parentClass;
            }

            return hierarchy;
        }

        public List<AdvplMethod> getMethods(bool inherited) {
            if (!inherited)
                return this.methods;

            List<AdvplMethod> inheritedMethods = new List<AdvplMethod>();
            
            foreach (AdvplClass c in this.getHierarchy()) {
                foreach (AdvplMethod m in c.methods) {
                    if (inheritedMethods.Contains(m))
                        inheritedMethods.Remove(m);

                    inheritedMethods.Add(m);
                }
            }

            return inheritedMethods;
        }

        public List<AdvplProperty> getProperties(bool inherited) {
            if (!inherited)
                return this.properties;

            List<AdvplProperty> inheritedPropertyes = new List<AdvplProperty>();

            foreach (AdvplClass c in this.getHierarchy()) {
                foreach (AdvplProperty p in c.properties) {
                    if (inheritedPropertyes.Contains(p))
                        inheritedPropertyes.Remove(p);

                    inheritedPropertyes.Add(p);
                }
            }

            return inheritedPropertyes;
        }
    }
}
